import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class Account {

	int saldo;
	
	public Account(int saldo){
		this.saldo=saldo;
		
	}
	
	public synchronized int withdraw(int amount){
		
		this.saldo=this.saldo-amount;
		return amount;
	}
	
	
	public synchronized void payIn(int payIn){
		this.saldo=this.saldo+payIn;
		
	}
	
	public int state(){
		return this.saldo;
	}
	
	
	public static void main(String args[]) throws InterruptedException {
		
		int SALDO_POCZATKOWE_KONTA=100;
		int KWOTA_OPERACJI=1;
		
		int ILOSC_KONT=100;
		int ILOSC_MAKLEROW=10;
		
		int sumaSaldStart = 0;
		int sumaSaldStop = 0;
		
		Account[] KONTA = new Account[ILOSC_KONT];
		Trader[] traderzy = new Trader[ILOSC_MAKLEROW];
		
		//przygotowanie kont
		for(int i=0;i<ILOSC_KONT;i++){
			KONTA[i]=new Account(SALDO_POCZATKOWE_KONTA);
			System.out.println(KONTA[i].state());
			sumaSaldStart+=KONTA[i].saldo;
			
		}
		System.out.println(sumaSaldStart+ "poczatek");
		
		//przygotowanie maklerow
		for(int i=0;i<ILOSC_MAKLEROW;i++){
			traderzy[i]=new Trader(KONTA);
			System.out.println(traderzy[i].getIdID());
		}
		
		
		//wystartowanie maklerow
		for(Trader trader : traderzy){
			trader.start();
		}
		
		for(Trader trader : traderzy)
        {
        	trader.join();
        }
		
		Thread.sleep(1000);
		
		//print stanu - dlaczego 
		for(int i=0;i<ILOSC_KONT;i++){
			sumaSaldStop+=KONTA[i].saldo;
			System.out.println(KONTA[i].state());
			
		}
		System.out.println(sumaSaldStop+ "koniec");
		
		
	}
	
}
 

 class Trader extends Thread{

	 Account[] accounts;
	 int operations=10000;
	 private static int idCounter=0;
	 private final int id;
	 Random losowanie = new Random();
	 
	
	 public Trader(Account[] accounts){
		 this.id=idCounter++;
		 this.accounts=accounts;
		 
	 }
	 
	 public int getIdID(){
		 return this.id;
		 }
	 
	public void run() {
		System.out.println("Jestem makler"+this.id);
		for(int i=0;i<operations;i++){
		int kontoWyp = losowanie.nextInt(this.accounts.length);
		int kontoWplac = losowanie.nextInt(this.accounts.length);
		
		Account konto1 = accounts[kontoWyp];
		Account konto2 = accounts[kontoWplac];
		
		
			
		Lock zamek  = new ReentrantLock();	
		zamek.lock();
		try{
		konto2.payIn(konto1.withdraw(1));
		}
		
		finally{
			zamek.unlock();
		}
			
		}
		System.out.println("Makler "+id+" skonczyl");
	}
	
}
 
 